A study on the distribution of Airbnb Listings in Singapore, and how has COVID-19 impacted them.
Singapore is one of the few countries that does not legalise short-term rentals for properties, a minimum stay of three months is still required for rental of properties as of 2019. Therefore, it was surprising to discover data sets for Airbnb listings located in Singapore in Inside Airbnb. But we shall dive deeper into this phenomenon of Airbnb being allowed in Singapore perhaps another day.
For this exercise, we will utilising those data sets to generate useful insights through:
For analysis purposes, the following data are used:
Airbnb listings for June 2019 and June 2021 from Inside Airbnb
Various geospatial data sets of choice extracted from SLA OneMap Service, using OneMap.Sg API
To begin the study, R packages will be used for efficiency and a more comprehensive analysis, such as tidyverse and sf etc.
packages <- c("readr", "maptools", "sf", "raster", "spatstat", "tmap", "tidyverse",
"plotly", "ggthemes")
for (p in packages) {
if (!require(p, character.only = T)) {
install.packages(p)
}
library(p, character.only = T)
}
We will first import in data using the Airbnb 2019 dataset, to see the distribution of listings. The analysis aims to uncover whether the distribution of Airbnb listings are affected by location factors such as near hotels or tourist attractions.
Kernel Density Maps will be used to unravel spatial patterns between the location of listings and various location factors mentioned earlier on. The advantage of using Kernel Density over Point Density is that the results are much more spatially accurate, because Point Density usually produces more steep edges which is not desirable. On the other hand, Kernel density gives smoother results that allows for plotting nicer visuals, which is crucial for getting substantial analysis insights.
airbnb_2019 <- read_csv("data/the2data/airbnb2019.csv")
airbnb_2021 <- read_csv("data/the2data/airbnb2021.csv")
sg_hotels <- read_csv("data/the2data/OneMapData/hotels.csv")
tourist_attractions <- read_csv("data/the2data/OneMapData/tourism.csv")
airbnb_2019 <- st_as_sf(airbnb_2019, coords = c("longitude", "latitude"), crs = 4326) %>%
st_transform(crs = 3414)
airbnb_2021 <- st_as_sf(airbnb_2021, coords = c("longitude", "latitude"), crs = 4326) %>%
st_transform(crs = 3414)
sg_hotels <- st_as_sf(sg_hotels, coords = c("Lng", "Lat"), crs = 4326) %>%
st_transform(crs = 3414)
For tourist attractions, an extra step is needed because there are NA values, so we have to drop them. If not, we will get an error “missing values in coordinates not allowed.”.
Checking and ensuring Projected Coordinates Systems of the sf object is correct
st_crs(airbnb_2019)
Coordinate Reference System:
User input: EPSG:3414
wkt:
PROJCRS["SVY21 / Singapore TM",
BASEGEOGCRS["SVY21",
DATUM["SVY21",
ELLIPSOID["WGS 84",6378137,298.257223563,
LENGTHUNIT["metre",1]]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
ID["EPSG",4757]],
CONVERSION["Singapore Transverse Mercator",
METHOD["Transverse Mercator",
ID["EPSG",9807]],
PARAMETER["Latitude of natural origin",1.36666666666667,
ANGLEUNIT["degree",0.0174532925199433],
ID["EPSG",8801]],
PARAMETER["Longitude of natural origin",103.833333333333,
ANGLEUNIT["degree",0.0174532925199433],
ID["EPSG",8802]],
PARAMETER["Scale factor at natural origin",1,
SCALEUNIT["unity",1],
ID["EPSG",8805]],
PARAMETER["False easting",28001.642,
LENGTHUNIT["metre",1],
ID["EPSG",8806]],
PARAMETER["False northing",38744.572,
LENGTHUNIT["metre",1],
ID["EPSG",8807]]],
CS[Cartesian,2],
AXIS["northing (N)",north,
ORDER[1],
LENGTHUNIT["metre",1]],
AXIS["easting (E)",east,
ORDER[2],
LENGTHUNIT["metre",1]],
USAGE[
SCOPE["Cadastre, engineering survey, topographic mapping."],
AREA["Singapore - onshore and offshore."],
BBOX[1.13,103.59,1.47,104.07]],
ID["EPSG",3414]]
tmap_mode("view")
tm_shape(airbnb_2019) + tm_dots(alpha = 0.4, col = "blue", size = 0.05) + tm_shape(sg_hotels) +
tm_dots(alpha = 0.4, col = "red", size = 0.05) + tm_shape(tourist_attractions) +
tm_dots(alpha = 0.4, col = "green", size = 0.05)